import type { FC, ReactNode } from 'react'
import React, { memo, useEffect, useState } from 'react'
import {
  Breadcrumb,
  Button,
  Dropdown,
  FormInstance,
  Layout,
  MenuProps,
  message,
  Modal,
  Space,
  Switch,
  theme,
  Tooltip,
  Typography
} from 'antd'
import {
  BulbFilled,
  CloudFilled,
  CompressOutlined,
  DownOutlined,
  ExclamationCircleOutlined,
  ExpandOutlined,
  MenuFoldOutlined,
  MenuUnfoldOutlined
} from '@ant-design/icons'
import { BreadcrumbItemType } from 'antd/es/breadcrumb/Breadcrumb'

import { HeaderWrapper } from '@/views/main/c-cpns/main-header/style'
import { myShallowEqual, useMyDispatch, useMySelector } from '@/store'
import { updateThemeConfig } from '@/utils/theme'
import {
  changeModeCheckedAction,
  changeThemeConfigAction,
  fetchClearLocalCoreData
} from '@/store/module/app'
import ColorPicker, { Color } from 'antd/es/color-picker'
import { localCache } from '@/utils/cache'
import { CacheType, RoutesPath, ThemeMode } from '@/global/constant'
import { reqLogout, reqUpdatePwd } from '@/service/module/app'
import { useLocation, useNavigate } from 'react-router-dom'
import PageModal from '@/components/page-modal'
import modalConfigUpdatePwd from '@/views/main/c-cpns/main-header/config/modal-update-pwd'
import usePageModal from '@/hooks/use-page-modal'
import { encryptData } from '@/utils/encrypt'

interface IProps {
  children?: ReactNode
  onCollapseClick: (collapsed: boolean) => void
}

enum UserAction {
  UpdatePwd = '修改密码',
  Logout = '退出登录'
}

const items: MenuProps['items'] = [
  {
    label: '修改密码',
    key: UserAction.UpdatePwd
  },
  {
    label: '退出登录',
    key: UserAction.Logout
  }
]

const MainHeader: FC<IProps> = (props) => {
  const dispatch = useMyDispatch()
  const navigate = useNavigate()
  const location = useLocation()
  /** 数据区 **/
  //  获取仓库数据
  const { publicKey, themeConfig, isModeChecked, userInfo, menuList } =
    useMySelector(
      (state) => ({
        publicKey: state.app.publicKey,
        themeConfig: state.app.themeConfig,
        isModeChecked: state.app.isModeChecked,
        userInfo: state.app.userInfo,
        menuList: state.app.menuList
      }),
      myShallowEqual
    )
  // 获取内置主题配置
  const {
    token: { colorBgContainer, colorPrimary }
  } = theme.useToken()
  // 菜单折叠状态数据
  const [collapsed, setCollapsed] = useState(false)
  // 主题颜色数据
  const [themeColor, setThemeColor] = useState<Color | string>(colorPrimary)
  // 决定是否全屏的状态
  const [isFull, setIsFull] = useState(false)
  // 面包屑数据
  const [breadCrumbs, setBreadCrumbs] = useState<BreadcrumbItemType[]>([])
  // 获取modal的实例
  // const pageModalRef = useRef<IModalComponentRef>(null)
  const { pageModalRef, onModalOk, onModalCancel } = usePageModal({ okCb })

  /** useEffect **/
  // 监听路由改变去更改面包屑数据
  useEffect(() => {
    if (!menuList.length) return
    const newMenuList = [...menuList]
    const { pathname } = location
    const newBreadCrumb: BreadcrumbItemType[] = []
    // 工作台是静态数据，手动指定
    if (pathname === RoutesPath.DashBoard) {
      newBreadCrumb.push({ title: '工作台' })
    } else {
      const result = recurveGetBreadCrumb(newMenuList, pathname)
      if (result) {
        newBreadCrumb.push(...result)
      }
    }
    setBreadCrumbs(newBreadCrumb)
  }, [location, menuList])

  /** 回调 **/
  // 递归获取面包屑数据
  function recurveGetBreadCrumb(menuList: any, pathname: string) {
    const titles: BreadcrumbItemType[] = []
    // 去菜单拿当前面包屑数据-根据当前路由找到当前菜单
    const targetMenu = menuList.find((menu: any) =>
      pathname.includes(menu.path)
    )
    if (targetMenu) {
      titles.push({ title: targetMenu.meta.title })
      // 递归子菜单
      if (targetMenu.children && targetMenu.children.length) {
        const result = recurveGetBreadCrumb(targetMenu.children, pathname)
        if (result) {
          titles.push(...result)
        }
      }
      return titles
    }
  }

  // 右上角 修改密码  |  退出登录 的点击
  const handleMenuClick: MenuProps['onClick'] = (e) => {
    switch (e.key) {
      case UserAction.UpdatePwd:
        handleUpdatePwd()
        break
      case UserAction.Logout:
        handleLogout()
        break
    }
  }
  const menuProps = {
    items,
    onClick: handleMenuClick
  }

  // 折叠/展开菜单
  function changeCollapsedStatus() {
    props.onCollapseClick(!collapsed)
    setCollapsed(!collapsed)
  }

  // 切换主题颜色
  function changeThemeColor(color: any) {
    // 整理color
    const { r, g, b, a } = color.metaColor
    const newColor = `rgba(${r},${g},${b},${a})`
    // 更新新的配置并返回
    const config = updateThemeConfig({ colorPrimary: newColor }, themeConfig)
    // 更新主题数据
    dispatch(changeThemeConfigAction(config))
    localCache.setCache(CacheType.THEME_CONFIG, config)
    // 修改当前颜色
    setThemeColor(color)
  }

  // 决定是否为全屏的回调
  function changeFullScreen() {
    const full = document.fullscreenElement
    // 判断当前是否为全屏
    if (!full) {
      // 进入全屏
      document.documentElement.requestFullscreen()
      setIsFull(true)
    } else {
      // 退出全屏
      document.exitFullscreen()
      setIsFull(false)
    }
  }

  // 日间模式和夜间模式的切换
  function onSwitchChange(checked: boolean) {
    const mode = checked ? ThemeMode.Dark : ThemeMode.Day
    const config = updateThemeConfig({ mode }, themeConfig)
    // 更新仓库主题配置
    dispatch(changeThemeConfigAction(config))
    dispatch(changeModeCheckedAction(checked))
    localCache.setCache(CacheType.THEME_CONFIG, config)
  }

  // 修改密码
  function handleUpdatePwd() {
    pageModalRef.current?.openModal()
  }

  // 退出登录的逻辑
  function handleLogout() {
    Modal.confirm({
      icon: <ExclamationCircleOutlined />,
      content: '您是否确认要退出登录',
      async onOk() {
        const res = await reqLogout()
        // 做出提示
        message.success(res.msg)
        // 删除本地记录
        dispatch(fetchClearLocalCoreData())
        // 跳转登录页
        navigate('/login')
      }
    })
  }

  // modal的确定与取消
  async function okCb(form: FormInstance | undefined) {
    const values = form?.getFieldsValue()
    const { newPassword1, newPassword, oldPassword } = values
    if (newPassword !== newPassword1) {
      message.error('两次输入的密码不一致~')
      return
    }
    // 通过验证，可以发请求修改密码
    const encryptStr = encryptData(publicKey, { newPassword, oldPassword })
    await reqUpdatePwd(encryptStr)
    // 请求完刷新一下当前页面会发送其他请求，这时候token已经失效了（会返回登录页）
    navigate(0)
  }

  // modal的取消

  return (
    <HeaderWrapper>
      <Layout.Header
        className="header"
        style={{ background: colorBgContainer }}
      >
        <div className="left">
          <Button
            className="toggle-menu"
            type="text"
            icon={collapsed ? <MenuFoldOutlined /> : <MenuUnfoldOutlined />}
            onClick={changeCollapsedStatus}
          />
          <Breadcrumb items={breadCrumbs} />
        </div>
        <div className="right">
          <div className="other-info">
            <Switch
              checkedChildren={<BulbFilled />}
              unCheckedChildren={<CloudFilled />}
              defaultChecked={isModeChecked}
              onChange={onSwitchChange}
            />
            <ColorPicker
              className="color-picker"
              value={themeColor}
              onChange={changeThemeColor}
            />
            <Tooltip title={isFull ? '退出全屏' : '全屏显示'}>
              <Button
                type="text"
                icon={isFull ? <CompressOutlined /> : <ExpandOutlined />}
                onClick={changeFullScreen}
              />
            </Tooltip>
          </div>
          <div className="userinfo">
            <img className="headPortrait" src={userInfo.headPortrait} alt="" />
            <Dropdown arrow menu={menuProps}>
              <Typography.Link>
                <Space>
                  {userInfo.nickName ?? '用户名'}
                  <DownOutlined />
                </Space>
              </Typography.Link>
            </Dropdown>
          </div>
        </div>
      </Layout.Header>
      {/*修改密码modal框*/}
      <PageModal
        ref={pageModalRef}
        modalConfig={modalConfigUpdatePwd}
        onOk={onModalOk}
        onCancel={onModalCancel}
      />
    </HeaderWrapper>
  )
}

export default memo(MainHeader)
